import { defineComponent, h, markRaw, reactive, toRaw, watch } from 'vue'
import DataNode from '../../ItemNode/DataNode'
import {
  ElButton,
  ElColorPicker,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadioButton,
  ElRadioGroup,
  ElSelect,
  ElSwitch,
  ElText
} from 'element-plus'
import classes from '../../ItemNode/ItemNode.module.css'
import { obj2Style, camel2Kebab } from '../../utils'
import { Minus, Plus } from '@element-plus/icons-vue'

export default class NText extends DataNode {
  isNText = true
  isDataDisplayNode = true
  styleDisplay = 'inline-block'

  constructor(node?: NText) {
    super(node)

    if (!node) {
      this.path = './components/NText/NText.tsx'
      this.name = '文本'

      this.props.style = {
        ...this.props.style,
        display: this.styleDisplay,
        maxWidth: '100%'
      }

      this.props.textStyle = {
        display: 'inline-block',
        width: '100%',
        fontSize: '16px',
        textAlign: 'start',
        textAlignLast: 'start',
        textIndent: '0',
        wordSpacing: 'normal',
        textShadow: '0px 0px 0px rgba(0, 0, 0, 0)'
      }

      this.props.dataUrl = ''
      this.props.dataFnable = false
      this.props.dataFn = `function () {\n  return '文本内容'\n}`
      this.props.content = '文本内容'
      this.props.tag = 'span'
      this.props.truncated = false
      this.props.lineClamp = null
      this.props.color = []
      this.props.textShadow = {
        color: 'rgba(0, 0, 0, 0)',
        blurRadius: '10px'
      }
    }

    watch(
      [() => this.props.truncated, () => this.props.lineClamp],
      ([newTruncated, newLineClamp]) => {
        Object.assign(this.props.textStyle, {
          display: 'inline-block',
          textOverflow: 'initial',
          whiteSpace: 'initial',
          '-webkit-box-orient': 'initial',
          '-webkit-line-clamp': 'initial',
          overflow: 'initial'
        })

        if (newLineClamp == null) {
          if (newTruncated) {
            Object.assign(this.props.textStyle, {
              display: 'inline-block',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
              overflow: 'hidden'
            })
          }
        } else {
          Object.assign(this.props.textStyle, {
            display: '-webkit-inline-box',
            '-webkit-box-orient': 'vertical',
            '-webkit-line-clamp': newLineClamp,
            overflow: 'hidden'
          })
        }
      }
    )

    watch(
      () => this.props.color,
      (newValue) => {
        if (newValue?.length > 1) {
          this.props.textStyle.color = 'transparent'
          this.props.textStyle.backgroundImage = `linear-gradient(${newValue.map((v) => v).join(', ')})`
          this.props.textStyle.backgroundClip = 'text'
        } else if (newValue?.length == 1) {
          this.props.textStyle.color = newValue[0]
        } else {
          this.props.textStyle.color = 'inherit'
        }
      },
      { deep: true, immediate: true }
    )

    const tagOptions = reactive([
      {
        label: '默认',
        value: 'span'
      },
      {
        label: '段落',
        value: 'p'
      },
      {
        label: '加粗',
        value: 'b'
      },
      {
        label: '斜体',
        value: 'i'
      },
      {
        label: '下标',
        value: 'sub'
      },
      {
        label: '上标',
        value: 'sup'
      },
      {
        label: '下划线',
        value: 'ins'
      },
      {
        label: '删除线',
        value: 'del'
      },
      {
        label: '标记',
        value: 'mark'
      }
    ])

    const textAlignOptions = reactive([
      {
        label: '左',
        value: 'start'
      },
      {
        label: '右',
        value: 'end'
      },
      {
        label: '居中',
        value: 'center'
      },
      {
        label: '两侧对齐',
        value: 'justify'
      }
    ])

    const pComponent = this.component
    this.component = markRaw(
      defineComponent(
        (props) => {
          watch(
            () => this.props.data,
            () => {
              if (this.props.dataFnable) this.props.content = this.props.data ?? ''
            },
            { immediate: true }
          )

          return () => (
            <pComponent>
              {h(this.props.tag, { style: this.props.textStyle }, this.props.content)}
            </pComponent>
          )
        },
        {
          name: 'NText'
        }
      )
    )

    const pView = this.view
    this.view = markRaw(
      defineComponent((props) => {
        this.props.color = ['#aaa']

        return () => (
          <pView>
            <this.component style={{ width: '100px', transform: 'scale(0.8)' }}></this.component>
          </pView>
        )
      })
    )

    const pParams = this.params
    this.params = markRaw(
      defineComponent(() => {
        const updateTextShadow = () => {
          if (this.props.textShadow.color)
            return (this.props.textStyle.textShadow = `0px 0px ${this.props.textShadow.blurRadius} ${this.props.textShadow.color}`)
          else delete this.props.textStyle.textShadow
        }

        return () => (
          <pParams>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                元素标签
              </ElText>
              <div class={classes['params-item-content']}>
                <ElSelect v-model={this.props.tag} size="small" teleported={false}>
                  {() =>
                    tagOptions.map((item) => (
                      <ElOption key={item.value} label={item.label} value={item.value}></ElOption>
                    ))
                  }
                </ElSelect>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                内容
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInput
                  v-model={this.props.content}
                  type="textarea"
                  autosize
                  size="small"
                ></ElInput>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                字体大小
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInput v-model={this.props.textStyle.fontSize} size="small"></ElInput>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                字间距
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInput v-model={this.props.textStyle.letterSpacing} size="small"></ElInput>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                字体颜色
              </ElText>
              <div class={classes['params-item-content']}>
                {this.props.color.map((c, index) => (
                  <ElColorPicker
                    modelValue={this.props.color[index]}
                    onUpdate:modelValue={(v) => (this.props.color[index] = v || '')}
                    show-alpha
                    size="small"
                    teleported={false}
                  ></ElColorPicker>
                ))}
                <ElButton
                  type="primary"
                  icon={Plus}
                  circle
                  onClick={() => this.props.color.push('#333')}
                  size="small"
                ></ElButton>
                <ElButton
                  type="danger"
                  icon={Minus}
                  circle
                  onClick={() => this.props.color.pop()}
                  size="small"
                ></ElButton>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                阴影
              </ElText>
              <div class={classes['params-item-content']}>
                颜色：
                <ElColorPicker
                  modelValue={this.props.textShadow.color}
                  onUpdate:modelValue={(v) => (this.props.textShadow.color = v || '')}
                  show-alpha
                  size="small"
                  teleported={false}
                  onChange={updateTextShadow}
                ></ElColorPicker>
                &nbsp; 范围：
                <ElInput
                  style={{ width: '50px' }}
                  v-model={this.props.textShadow.blurRadius}
                  size="small"
                  onChange={updateTextShadow}
                ></ElInput>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                水平对齐
              </ElText>
              <div class={classes['params-item-content']}>
                <ElRadioGroup
                  modelValue={this.props.textStyle.textAlign}
                  onUpdate:modelValue={(v) =>
                    (this.props.textStyle.textAlign = this.props.textStyle.textAlignLast = v)
                  }
                  size="small"
                >
                  {() =>
                    textAlignOptions.map((item) => (
                      <ElRadioButton
                        key={item.value}
                        label={item.label}
                        value={item.value}
                      ></ElRadioButton>
                    ))
                  }
                </ElRadioGroup>
              </div>
            </div>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                最大行数
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInputNumber
                  modelValue={this.props.lineClamp}
                  onUpdate:modelValue={(v) => (this.props.lineClamp = v)}
                  min={1}
                  step={1}
                  size="small"
                ></ElInputNumber>
              </div>
            </div>
            {this.props.lineClamp == null ? (
              <div class={classes['params-item']}>
                <ElText class={classes['params-item-label']} type="info">
                  显示省略号
                </ElText>
                <div class={classes['params-item-content']}>
                  <ElSwitch
                    modelValue={this.props.truncated}
                    onUpdate:modelValue={(v) => (this.props.truncated = v)}
                    size="small"
                  ></ElSwitch>
                </div>
              </div>
            ) : (
              <></>
            )}
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                缩进
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInputNumber
                  modelValue={Number.parseInt(this.props.textStyle.textIndent)}
                  onUpdate:modelValue={(v) => (this.props.textStyle.textIndent = `${v || 0}em`)}
                  min={0}
                  step={1}
                  size="small"
                ></ElInputNumber>
              </div>
            </div>
          </pParams>
        )
      })
    )
  }

  toVue(): SfcObj {
    const sfcObj = super.toVue()
    const name = sfcObj.name
    const dataVar = sfcObj.dataVar
    const [uuid0, uuid1] = this.uuid.split('-')
    const contentVar = `${name}_${uuid0}_content`
    const className = `${camel2Kebab(name)}-${uuid1}`

    sfcObj.imports = {
      ...sfcObj.imports,
      vue: {
        ...sfcObj.imports.vue,
        ref: 'ref',
        watch: 'watch'
      }
    }

    sfcObj.script = `
${sfcObj.script}
watch(${dataVar}, () => {
  ${contentVar}.value = ${dataVar}.value ?? ''
})
      `

    sfcObj.template = sfcObj.template.replace(
      '<slot></slot>',
      `
  <${this.props.tag} class="${className}-content">${this.props.dataUrl ? `{{${contentVar}}}` : this.props.content}</${this.props.tag}>
      `
    )

    sfcObj.style += `
.${className}-content ${obj2Style(toRaw(this.props.textStyle))}
      `

    return sfcObj
  }
}
